/*
 * Copyright © 2004-2014 chenYuan. All rights reserved.
 * @Website:wwww.jspx.net
 * @Mail:39793751@qq.com
 * @author: chenYuan , 陈原
 * @License: Jspx.net Framework Code is open source (LGPL)，Jspx.net Framework 使用LGPL 开源授权协议发布。
 * @jvm:jdk1.6+  x86/amd64
 *
 */
package com.jspx.boot;

import com.jspx.boot.environment.JspxConfiguration;
import com.jspx.boot.environment.EnvironmentTemplate;
import com.jspx.boot.environment.Environment;
import com.jspx.boot.environment.Log4jConfig;
import com.jspx.boot.environment.impl.Log4jConfigImpl;
import com.jspx.cache.JSCacheManager;
import com.jspx.sioc.IocContext;
import com.jspx.sioc.AopAppBean;
import com.jspx.sioc.BeanFactory;
import com.jspx.sioc.factory.EntryFactory;
import com.jspx.sioc.config.ConfigureContext;
import com.jspx.scriptmark.Configurable;
import com.jspx.scriptmark.config.TemplateConfigurable;
import com.jspx.txweb.config.TXWebConfigManager;
import com.jspx.txweb.dispatcher.Dispatcher;
import com.jspx.txweb.evasive.Configuration;
import com.jspx.txweb.evasive.EvasiveConfiguration;
import com.jspx.utils.FileUtil;
import com.jspx.utils.StringUtil;
import com.jspx.utils.SystemUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletContextListener;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

/**
 * Created by IntelliJ IDEA.
 * User: 陈原
 * Date: 2007-12-1
 * Time: 17:51:48
 */
public class JspxCoreListener implements ServletContextListener {

    private final static Logger log = LoggerFactory.getLogger(JspxCoreListener.class);
    static private int startTimes = 0;
    private String copyright = StringUtil.empty;

    public JspxCoreListener() {

    }


    public static boolean isRun = false;

    public long getRunDate() {
        return runDate;
    }

    private long runDate = System.currentTimeMillis();

    static public boolean isRun() {
        return isRun;
    }

    private String defaultPath = null;

    public void setDefaultPath(String defaultPath) {
        if (!defaultPath.endsWith("/")&&!defaultPath.endsWith("\\")) defaultPath = defaultPath + "/";
        this.defaultPath = defaultPath;
    }

    public void contextInitialized(javax.servlet.ServletContextEvent servletContextEvent) {

        boolean isAndroid = SystemUtil.isAndroid();
        //开始不能调用时间,调用了时间设置不了时区
        copyright = Environment.frameworkName + " " + Environment.version + " " + Environment.licenses + " Powered By chenYuan ";

        log.info("-" + copyright + " start-" + startTimes++);
        //////初始化环境变量 begin

        JspxConfiguration jspxConfiguration = EnvFactory.getBaseConfiguration();
        if (!StringUtil.isNULL(defaultPath)) jspxConfiguration.setDefaultPath(defaultPath);
        EnvironmentTemplate envTemplate = EnvFactory.getEnvironmentTemplate();
        //路径配置

        try {
            envTemplate.createPathEnv(jspxConfiguration.getDefaultPath());
        } catch (Exception e) {
            e.printStackTrace();
        }

        //jdbc配置
        if (!FileUtil.isFileExist(jspxConfiguration.getDefaultPath() + Environment.jspx_properties_file)) {
            String info = "not found " + Environment.jspx_properties_file + ",不能找到基本的配置文件" + Environment.jspx_properties_file + ",构架将不能正常工作";
            log.info(info);
            log.info("你需要放入" + Environment.jspx_properties_file + "配置文件,然后重新启动java服务器");
            return;
        }


        envTemplate.createJspxEnv(jspxConfiguration.getDefaultPath() + Environment.jspx_properties_file);
        log.info("create log4j config");
        Log4jConfig log4jConfig = new Log4jConfigImpl();
        log4jConfig.createConfig();


        log.info("create jspx.net system Environment");
        //环境配置
        envTemplate.createSystemEnv();
        //修复占位符号
        log.info("create placeholder Environment");
        try {
            envTemplate.restorePlaceholder();
        } catch (Exception e) {
            e.printStackTrace();
        }

        //////初始化环境变量 end

        log.info("default Path=" + envTemplate.getString(Environment.defaultPath));
        log.info("java.library.path=" + System.getProperty("java.library.path"));


        //////////////////////初始化脚本语言环境 begin
        Configurable templateConfigurable = TemplateConfigurable.getInstance();
        templateConfigurable.setSearchPath(new String[]{envTemplate.getString(Environment.defaultPath), envTemplate.getString(Environment.templatePath)});
        templateConfigurable.setAutoIncludes(StringUtil.split(envTemplate.getString(Environment.autoIncludes), StringUtil.SEMICOLON));
        templateConfigurable.setAutoImports(StringUtil.split(envTemplate.getString(Environment.autoImports), StringUtil.SEMICOLON));
        templateConfigurable.setGlobalMap(envTemplate.getVariableMap());
        //////////////////////初始化脚本语言环境 end

        ////////////导入Ioc配置 begin
        IocContext iocContext = ConfigureContext.getInstance();
        iocContext.setConfigFile(jspxConfiguration.getIocConfigFile());

        EntryFactory beanFactory = (EntryFactory) EnvFactory.getBeanFactory();
        beanFactory.setIocContext(iocContext);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //应用平台AOP 类似windows的服务,后台运行，平台启动运行，和结束运行


        Configuration evasiveConfiguration = EvasiveConfiguration.getInstance();
        evasiveConfiguration.setFileName(envTemplate.getString(Environment.evasive_config));

        SystemUtil.encode = envTemplate.getString(Environment.systemEncode, SystemUtil.OS == SystemUtil.WINDOWS ? "GBK" : "UTF-8");
        ////////////////////////AOP begin
        if (!isAndroid) {
            log.info("repairEncode=" + envTemplate.getString(Environment.repairEncode));
            log.info("httpServer=" + envTemplate.getString(Environment.httpServerName));
            log.info("user.timezone=" + System.getProperty("user.timezone"));
        }

        if (envTemplate.getBoolean(Environment.AopBoot)) {
            AopAppBean aopAppBean = (AopAppBean) beanFactory.getBean(Environment.AopBootBean);
            try {
                if (aopAppBean != null)
                    aopAppBean.init();
            } catch (Exception e) {
                log.error( Environment.AopBootBean + " " + e.getLocalizedMessage());
            }
        }

        if (envTemplate.getBoolean(Environment.AopEndpointPublish)) {
            AopAppBean aopAppBean = (AopAppBean) beanFactory.getBean(Environment.AopEndpointPublish, envTemplate.getString(Environment.SoapWebServiceNamespace));
            try {
                if (aopAppBean != null)
                    aopAppBean.init();
            } catch (Exception e) {
                log.error(Environment.AopBootBean + " " + e.getLocalizedMessage());
            }
        }

/*

        if (isAndroid)
        {
            LoggerFactory.setLoggerProvider(new AndroidLoggerProvider());
        }
        else
        {
            try {
                //判断log4j是否存在
                Class.forName("org.apache.log4j.LogManager");
                LoggerFactory.setLoggerProvider(new Log4jLoggerProvider());
                log = LoggerFactory.getLogger(JspxCoreListener.class);
            } catch (Exception e) {
                LoggerFactory.printError("not find log4j,没有找到Log4j");
            }
        }
 */

        ////////////////////////AOP end
        Dispatcher.getInstance();
        log.info("-" + copyright + " start completed " + (isAndroid ? "for Android" : " J2SDK"));
        isRun = true;

    }

    public void contextDestroyed(javax.servlet.ServletContextEvent servletContextEvent) {
        log.info(Environment.frameworkName + " " + copyright + " shutdown start");

        //关闭访问页面begin
        Dispatcher.shutdown();
        log.info("close dispatcher");
        //关闭访问页面end

        BeanFactory beanFactory = EnvFactory.getBeanFactory();
        if (beanFactory.containsBean(Environment.AopBootBean)) {
            AopAppBean aopAppBean = (AopAppBean) beanFactory.getBean(Environment.AopBootBean);
            if (aopAppBean != null)
                try {
                    aopAppBean.destroy();
                } catch (Exception e) {
                    e.printStackTrace();
                }
        }
        beanFactory.shutdown();
        log.info("bean factory shutdown");


        //关闭缓存和线程begin
        JSCacheManager.shutdown();
        log.info("JSCache shutdown");
        //关闭缓存和线程end

        //TXWeb配置卸载begin
        TXWebConfigManager.getInstance().clear();
        log.info("TXWeb config clean");
        //TXWeb配置卸载end

        //Evasive配置卸载begin
        EvasiveConfiguration.getInstance().shutdown();
        log.info("Evasive config clean");
        //Evasive配置卸载begin

        //卸载jdbc驱动begin
        Enumeration<Driver> drivers = DriverManager.getDrivers();
        Driver d = null;
        while (drivers.hasMoreElements()) {
            try {
                d = drivers.nextElement();
                DriverManager.deregisterDriver(d);
                log.info(String.format("jdbc driver %s deregister", d));
            } catch (SQLException ex) {
                log.error(String.format("Error deregistering driver %s", d));
            }
        }
        //卸载jdbc驱动end

        //关闭定时器和其他线程begin

        //安卓系统跳过这里，否则会有错误
        if (!SystemUtil.isAndroid())
        {
            ThreadLocalImmolate threadLocalImmolate = new ThreadLocalImmolate(true);
            log.info("ThreadLocal shutdown count is " + threadLocalImmolate.immolate());
        }
        //关闭定时器和其他线程end

        isRun = false;
        log.info(Environment.frameworkName + " " + copyright + " dispatcher shutdown completed ");
    }
}